package com.calabar.flume.tcp.server;

import com.calabar.flume.tcp.websocket.server.WebSocketHandler;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.FixedLengthFrameDecoder;
import io.netty.handler.codec.bytes.ByteArrayDecoder;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;

import java.util.List;

/**
 * 协议初始化解码器.
 * <p>
 * 用来判定实际使用什么协议.</b>
 */
public class MySocketChooseHandler extends ByteToMessageDecoder {
    /**
     * 默认长度为8000
     */
    private static final int MAX_LENGTH = 8 * 1000;
    /**
     * WebSocket握手的协议前缀
     */
    private static final String WEBSOCKET_PREFIX = "GET /ws";


    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        String protocol = getBufStart(in);

        ChannelPipeline pipeline = ctx.pipeline();
        if (protocol.startsWith(WEBSOCKET_PREFIX)) {
            // websocket 处理
            webSockethandlers(pipeline);
        } else {
            tcphandlers(pipeline);
        }
        in.resetReaderIndex();
        pipeline.remove(this);
    }

    private String getBufStart(ByteBuf in) {
        int length = in.readableBytes();
        if (length > MAX_LENGTH) {
            length = MAX_LENGTH;
        }

        // 标记读位置
        in.markReaderIndex();
        byte[] content = new byte[length];
        in.readBytes(content);
        return new String(content);
    }


    public void webSockethandlers(ChannelPipeline pipeline) {
        //HttpServerCodec: 针对http协议进行编解码
        pipeline.addLast("httpServerCodec", new HttpServerCodec());
        //ChunkedWriteHandler分块写处理，文件过大会将内存撑爆
        pipeline.addLast("chunkedWriteHandler", new ChunkedWriteHandler());
        /**
         * 作用是将一个Http的消息组装成一个完成的HttpRequest或者HttpResponse，那么具体的是什么
         * 取决于是请求还是响应, 该Handler必须放在HttpServerCodec后的后面
         */
        pipeline.addLast("httpObjectAggregator", new HttpObjectAggregator(8192));

        //用于处理websocket, /ws为访问websocket时的uri
        pipeline.addLast("webSocketServerProtocolHandler", new WebSocketServerProtocolHandler("/ws"));

        pipeline.addLast("myWebSocketHandler", new WebSocketHandler());
    }

    public void tcphandlers(ChannelPipeline pipeline) {
        pipeline.addLast(new FixedLengthFrameDecoder(8 * 1000));
        pipeline.addLast(new ByteArrayDecoder());
        pipeline.addLast(new MyServerHandler());
    }
}